package com.springboot.file.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 线程池配置类 - 优化版本
 * 针对Excel数据处理进行了特别优化
 */
@Slf4j
@Configuration
@EnableAsync // 开启异步调用
public class ThreadPoolConfig {
    @Value("${task.pool.corePoolSize}")
    private int corePoolSize;
    @Value("${task.pool.maxPoolSize}")
    private int maxPoolSize;
    @Value("${task.pool.keepAliveSeconds}")
    private int keepAliveSeconds;
    @Value("${task.pool.queueCapacity}")
    private int queueCapacity;
    @Value("${task.pool.awaitTerminationSeconds}")
    private int awaitTerminationSeconds;
    @Value("${task.pool.threadNamePrefix}")
    private String threadNamePrefix;
    @Value("${task.pool.waitForTasksToCompleteOnShutdown}")
    private boolean waitForTasksToCompleteOnShutdown;
    @Value("${task.pool.allowCoreThreadTimeOut}")
    private boolean allowCoreThreadTimeOut;

    @Bean
    public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
        log.info("正在初始化Excel导入线程池 - 核心线程数:{}, 最大线程数:{}, 队列容量:{}",
                corePoolSize, maxPoolSize, queueCapacity);
                
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //配置核心线程数
        executor.setCorePoolSize(corePoolSize);
        //配置最大线程数
        executor.setMaxPoolSize(maxPoolSize);
        //配置线程池队列容量
        executor.setQueueCapacity(queueCapacity);
        //配置线程池维护线程所允许的空闲时间
        executor.setKeepAliveSeconds(keepAliveSeconds);
        //配置线程名称前缀
        executor.setThreadNamePrefix(threadNamePrefix);
        
        // 使用自定义的拒绝策略，先记录日志再使用CallerRunsPolicy
        executor.setRejectedExecutionHandler(new RejectedExecutionHandler() {
            private final ThreadPoolExecutor.CallerRunsPolicy callerRunsPolicy = new ThreadPoolExecutor.CallerRunsPolicy();
            
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                log.warn("线程池队列已满，任务将在调用线程中执行。当前活动线程数: {}, 队列中等待任务数: {}", 
                        executor.getActiveCount(), executor.getQueue().size());
                callerRunsPolicy.rejectedExecution(r, executor);
            }
        });
        
        //配置线程池是否允许核心线程超时
        executor.setAllowCoreThreadTimeOut(allowCoreThreadTimeOut);
        //配置线程池等待任务完成的超时时间
        executor.setWaitForTasksToCompleteOnShutdown(waitForTasksToCompleteOnShutdown);
        //配置线程池等待时间
        executor.setAwaitTerminationSeconds(awaitTerminationSeconds);
        //配置线程池的线程工厂
        executor.setThreadFactory(Executors.defaultThreadFactory());
        
        //初始化线程池
        executor.initialize();
        
        // 预启动所有核心线程，预热线程池
        executor.getThreadPoolExecutor().prestartAllCoreThreads();
        log.info("Excel导入线程池初始化完成，已预启动{}个核心线程", corePoolSize);
        
        //返回线程池
        return executor;
    }
}